package designPatterns

import kotlin.math.sqrt

/**
 * @chineseName : 开闭原则
 * @description : 软件中的对象(类，模块，函数等等)对扩展应该是开放的（即可以继承），但是对修改是封闭的（因为这些对象会在多处用到，如果你修改了会影响到其他地方）
 * @scene : 不同图形的面积计算
 * @author : lwl
 * @createTime : 2022/5/11 13:05
 */

fun main() {
    val area1: ICalculationArea = CalculationArea()
    println(area1.circle(10.0))
    val area2: ICalculationArea = CalculationAreaExt()
    area2.circle(10.0)
}

/**
 * 面积计算的接口
 */
interface ICalculationArea {

    /**
     * 计算矩形面积
     */
    fun rectangle(x: Double, y: Double): Double

    /**
     * 计算三角形面积
     *
     * 海伦公式：S = √ p(p - a)(p - b)(p - c) 其中 p = (a + b + c)/2
     */
    fun triangle(x: Double, y: Double, z: Double): Double

    /**
     * 计算圆形面积
     */
    fun circle(r: Double): Double

}

/**
 * 面积计算实现
 */
open class CalculationArea : ICalculationArea {
    companion object {
        private const val Pai: Double = 3.14
    }

    override fun rectangle(x: Double, y: Double): Double {
        return x * y
    }

    override fun triangle(x: Double, y: Double, z: Double): Double {
        val p = (x + y + z) / 2
        return sqrt(p * (p - x) * (p - y) * (p - z))
    }

    override fun circle(r: Double): Double {
        return Pai * r * r
    }
}

/**=============================现在如果计算圆面积想要精度更加高=============================**/
//如果直接去修改CalculationArea类的肯定是不合理的，因为有些地方又不需要高精度，所以对其进行继承，修改其中想要修改的地方即可

/**
 * 扩展CalculationArea，实现自己的需求
 */
open class CalculationAreaExt : CalculationArea() {
    companion object {
        private const val Pai: Double = 3.141592653
    }

    override fun circle(r: Double): Double {
        return Pai * r * r
    }

}